package com.stormpath.sdk.impl.config; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.ValueNode; import com.stormpath.sdk.impl.io.Resource; import com.stormpath.sdk.lang.Assert; import java.io.IOException; import java.io.InputStream; import java.util.HashMap; import java.util.Iterator; import java.util.Map; public class JSONPropertiesSource implements PropertiesSource { private final Resource resource; public JSONPropertiesSource(Resource resource) { Assert.notNull(resource, "resource argument cannot be null."); this.resource = resource; } @Override public Map<String, String> getProperties() { Map<String, String> map = new HashMap<>(); try (InputStream in = resource.getInputStream()) { // InputStream is null when file is configured, but not found if (in != null) { getFlattenedMap("", new ObjectMapper().readTree(resource.getInputStream()), map); } } catch (IOException e) { throw new IllegalArgumentException("Unable to read resource [" + resource + "]: " + e.getMessage(), e); } return map; } private void getFlattenedMap(String currentPath, JsonNode jsonNode, Map<String, String> map) { if (jsonNode.isObject()) { ObjectNode objectNode = (ObjectNode) jsonNode; Iterator<Map.Entry<String, JsonNode>> iter = objectNode.fields(); String pathPrefix = currentPath.isEmpty() ? "" : currentPath + "."; while (iter.hasNext()) { Map.Entry<String, JsonNode> entry = iter.next(); getFlattenedMap(pathPrefix + entry.getKey(), entry.getValue(), map); } } else if (jsonNode.isArray()) { ArrayNode arrayNode = (ArrayNode) jsonNode; for (int i = 0; i < arrayNode.size(); i++) { getFlattenedMap(currentPath + "[" + i + "]", arrayNode.get(i), map); } } else if (jsonNode.isValueNode()) { ValueNode valueNode = (ValueNode) jsonNode; map.put(currentPath, valueNode.asText()); } } }